package com.noahsloan.groovy.util

import org.codehaus.groovy.runtime.InvokerHelperimport groovy.lang.MissingMethodException

/**
 * Implements the prototype and properties patterns. Missing methods and 
 * properties are delegated to the prototype, but any arbitrary property
 * can be added, which will override properties and methods from the
 * prototype.
 * 
 * @author noah
 *
 */
public class DelegateObject extends Expando {

	/**
	 * This object's prototype.
	 */
	def prototype
	
	DelegateObject() {}
	DelegateObject(prototype) {
		this.prototype = prototype
	}
	DelegateObject(prototype,Map properties) {
		super(new LinkedHashMap(properties))
		this.prototype = prototype
	}
	
	def methodMissing(String name,args) {
		def method = this[name]
		return method ? method.call((Object[])args) :
			InvokerHelper.invokeMethodSafe(prototype,name,args)
	}
	
	def propertyMissing(String name) {
		try {
			return prototype[name]
		} catch (MissingPropertyException e) {
			return null
		}
	}
	
	String toString() {
		if(toString) {
			toString.delegate = this
			return toString.call()
		} else {			
			return prototype.toString() 
		}
	}
}
